package helper

import (
	"strconv"
	"strings"
	"time"
)

// This defines some layout to help to format time to string.
//
// For example:
//
// now := time.Date(2020, 5, 23, 21, 30, 12, 0, time.Local)
//
// now.Format(DateFormat) 		=>		2020-05-23
// now.Format(TimeFormat) 		=>		21:30:12
// now.Format(DateTimeFormat) 	=>		2020-05-23 21:30:12
// now.Format(time.RFC3339)		=>  	2020-05-23T21:30:12+08:00
//
const (
	// DateFormat convert time.Time to `yyyy-MM-dd` format.
	DateFormat = "2006-01-02"
	// TimeFormat convert time.Time to `HH:mm:ss` format.
	TimeFormat = "15:04:05"
	// DateTimeFormat convert time.Time to `yyyy-MM-dd HH:mm:ss` format.
	DateTimeFormat               = "2006-01-02 15:04:05"
	DateTimeWithoutSecondsFormat = "2006-01-02 15:04"
	//	excel单元格默认时间格式
	ExcelDataTimeFormat  = "01/02/06 15:04"
	ExcelDataTimeFormat2 = "2006/01/02 15:04"
	ExcelDataFormat      = "01/02/06"
	ExcelDataFormat2     = "2006/01/02"
	ExcelDataFormat3     = "01-02-06"
	ExcelDataFormat4     = "02/1/06 15:04"
	ExcelDataFormat5     = "02/01/06 15:04"
)

var DateTimeMap = map[string]string{
	"YYYY-MM-DD HH:mm":    DateTimeWithoutSecondsFormat,
	"YYYY-MM-DD HH:mm:ss": DateTimeFormat,
	"MM/DD/YY HH:mm":      ExcelDataTimeFormat,
	"MM/DD/YY":            ExcelDataFormat,
	"YYYY-MM-DD":          DateFormat,
	"HH:mm:ss":            TimeFormat,
	"YYYY/MM/DD HH:mm":    ExcelDataTimeFormat2,
	"YYYY/MM/DD":          ExcelDataFormat2,
	"MM-DD-YY":            ExcelDataFormat3,
	"yyyy-MM-dd HH:mm:ss": DateTimeFormat,
	"yyyy-MM-dd":          DateFormat,
	"DD/M/YY HH:mm":       ExcelDataFormat4,
	"DD/MM/YY HH:mm":      ExcelDataFormat5,
}

// TimeToString convert a time to string using traditional format.
//
// yyyy-MM-dd			=>	2020-05-23
// HH:mm:ss				=>	21:30:12
// yyyy-MM-dd HH:mm:ss	=>	2020-05-23 21:30:12
func TimeToString(time time.Time, format string) string {
	year := strconv.Itoa(time.Year())
	month := strconv.Itoa(int(time.Month()))
	day := strconv.Itoa(time.Day())
	hour := strconv.Itoa(time.Hour())
	minute := strconv.Itoa(time.Minute())
	second := strconv.Itoa(time.Second())

	if len(month) < 2 {
		month = "0" + month
	}
	if len(day) < 2 {
		day = "0" + day
	}
	if len(hour) < 2 {
		hour = "0" + hour
	}
	if len(minute) < 2 {
		minute = "0" + minute
	}
	if len(second) < 2 {
		second = "0" + second
	}

	result := strings.ReplaceAll(format, "yyyy", year)
	result = strings.ReplaceAll(result, "MM", month)
	result = strings.ReplaceAll(result, "dd", day)
	result = strings.ReplaceAll(result, "HH", hour)
	result = strings.ReplaceAll(result, "mm", minute)
	result = strings.ReplaceAll(result, "ss", second)

	return result
}

func Format(time time.Time, format string) string {
	var theTime string

	dateFormat, ok := DateTimeMap[format]
	if ok {
		theTime = time.Format(dateFormat)
	} else {
		theTime = time.Format(DateTimeFormat)
	}

	return theTime
}

func StringToTime(timeStr string, format string) (time.Time, error) {
	loc, _ := time.LoadLocation("Local")
	theTime := time.Time{}
	var err error

	dateFormat, ok := DateTimeMap[format]
	if ok {
		theTime, err = time.ParseInLocation(dateFormat, timeStr, loc)
	} else {
		theTime, err = time.ParseInLocation(DateTimeFormat, timeStr, loc)
	}

	return theTime, err
}

func ParseExcelDateTime(timeStr string, format string) (time.Time, error) {
	t, err := StringToTime(timeStr, format)
	if err != nil {
		// 遍历map
		for key := range DateTimeMap {
			t, err = StringToTime(timeStr, key)
			if err == nil {
				break
			}
		}
	}

	return t, err
}

// GetZeroTime 获取某一天的 0 点时间
func GetZeroTime(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
}

// GetMondayOfWeek 获取本周周一
func GetMondayOfWeek(t time.Time) time.Time {
	day := GetZeroTime(t)
	if t.Weekday() != time.Monday {
		offset := int(time.Monday - t.Weekday())
		if offset > 0 {
			offset = -6 // 周日
		}
		day = day.AddDate(0, 0, offset)
	}
	return day
}

// GetFirstDayOfMonth 获取本月一号日期
func GetFirstDayOfMonth(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local)
}

// GetQuarterDay 获取本季度第一天
func GetQuarterDay(t time.Time) time.Time {
	firstDay := time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.Local)
	month := int(t.Month())
	switch {
	case month >= 1 && month <= 3:
		return firstDay
	case month >= 4 && month <= 6:
		return time.Date(t.Year(), 4, 1, 0, 0, 0, 0, time.Local)
	case month >= 7 && month <= 9:
		return time.Date(t.Year(), 7, 1, 0, 0, 0, 0, time.Local)
	case month >= 10 && month <= 12:
		return time.Date(t.Year(), 10, 1, 0, 0, 0, 0, time.Local)
	}
	return firstDay
}

// GetFirstDayOfYear 获取本年第一天
func GetFirstDayOfYear(t time.Time) time.Time {
	return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.Local)
}
